package com.ttpai.boot.lbs.service;

import com.ttpai.boot.lbs.model.RoutePlanReportVO;
import com.ttpai.boot.lbs.util.CalendarUtil;
import com.ttpai.boot.lbs.util.LLUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by kail on 2017/2/24.
 */
@Service
public class DynamicRoutePlanService {

    private static final Logger logger = LoggerFactory.getLogger(DynamicRoutePlanService.class);

    private static final int CHECK_USE_MIN = 29; // 检测一辆车需要多长时间

    @Autowired
    private RoutePlanReportService reportService;

    public Map<String, List<RoutePlanReportVO>> buildDynamicPlain(Date date, String city) {
        List<List<RoutePlanReportVO>> doPlanNotFormat = this.doPlanNotFormat(date, city);
        return CommonService.buildDynamicPlain(doPlanNotFormat);
    }

    private List<List<RoutePlanReportVO>> doPlanNotFormat(Date date, String city) {

        List<RoutePlanReportVO> reportVOS = reportService.selectRoutePlanReportByDate(date, city);


        List<List<RoutePlanReportVO>> planRoutes = new ArrayList<>();

        for (RoutePlanReportVO startPoint : reportVOS) {
            if (null == startPoint.getLng() || startPoint.getLng().equals(0D)) {
                continue;
            }
            // 从第一个开始，如果没有被分配，则该点为起点
            if (!startPoint.getZhanyong()) {
                ArrayList<RoutePlanReportVO> planLine = new ArrayList<>();
                planLine.add(startPoint);
                planRoutes.add(planLine);

                // 从起点开始查找下一条路线
                findNextPointFromStart(planLine, startPoint, reportVOS);

            }
        }
        return planRoutes;
    }

    /**
     * @param line       当前路线
     * @param startPoint 开始路线
     * @param plainDatas 原始数据
     */
    static void findNextPointFromStart(List<RoutePlanReportVO> line, RoutePlanReportVO startPoint, List<RoutePlanReportVO> plainDatas) {
        startPoint.setZhanyong(true); // 标记起始点为占用状态

        // 遍历所有原始数据，判断下一条路线
        for (int i = 0; i < plainDatas.size(); i++) {
            RoutePlanReportVO curPoint = plainDatas.get(i);
            if (null == curPoint.getLng() || curPoint.getLng().equals(0D)) {
                continue;
            }
            // 起始点的检测结束时间
            Date checkEndTime = CalendarUtil.add(startPoint.getCheckTime(), CHECK_USE_MIN, Calendar.MINUTE);
            // 开始点的检测结束时间为启程时间
            long starTime = checkEndTime.getTime();

            // 没有被占用，并且 检测时间是在第一辆车检测完成之后
            if (!curPoint.getZhanyong() && !curPoint.getCheckTime().before(checkEndTime)) {
                RoutePlanReportVO nextPoint = null; // 找出下一个点


                Long minCost = Long.MAX_VALUE; // 找到下一点的做小成本 = 消除距离后的时间差(时间最短) + 路程耗时(距离最短)
                for (int j = i; j < plainDatas.size(); j++) {
                    RoutePlanReportVO cur = plainDatas.get(j);
                    if (!cur.getZhanyong()) {
                        // 两个距离直接需要的秒数
                        double sec = LLUtil.rightAngleDistance2Sec(startPoint.getLng(), startPoint.getLat(), cur.getLng(), cur.getLat());

                        // 结束时间 - 路程所需时间，消除路程所需时间
                        long endTime = CalendarUtil.add(cur.getCheckTime(), -(int) sec, Calendar.SECOND).getTime();

                        if (starTime < endTime) {
                            // 消除距离后的时间差(时间最短) + 路程耗时(距离最短，距离权重大于时间全总)
                            long curCost = (endTime - starTime) / 1000 + (long) sec * 5; // 1043735
                            if (curCost < minCost) {
                                minCost = curCost; //
                                nextPoint = cur;
                            }
                        }
                    }
                }

                // 遍历所有点，如果找的话就继续，找不到的话不找了
                if (null != nextPoint) {
                    line.add(nextPoint); // 放入路线中
                    findNextPointFromStart(line, nextPoint, plainDatas); // 找的的点作为起始点，开始找下一个
                    break; // 没找到下一个，就不找了，开始计算下一条路线
                }
            }
        }
    }

}
